
from celery import shared_task
import time
from celery import shared_task
from django.db import transaction, close_old_connections, DatabaseError, OperationalError
from django.db.models import F
from django.utils import timezone
from django_redis import get_redis_connection
from pymysql import IntegrityError
from celery.utils.log import get_task_logger
from goods.models import SeckillGoods, Goods
from orders.models import Order, SeckillOrder
from utils.redis_utils import preload_stock_to_redis, get_goods_detail, RedisHelper, get_all_seckill_goods_ids

logger = get_task_logger(__name__)
# @shared_task
# def example_task(param1, param2):
#     """示例异步任务"""
#     print(f"开始执行任务，参数：{param1}, {param2}")
#     time.sleep(5)  # 模拟耗时操作
#     result = f"任务完成：{param1}, {param2}"
#     print(result)
#     return result
#

@shared_task(bind=True,max_retries=3)
def createOrder(self,goods_id,user_id,max_retries=3, retry_delay=1):

    """
    创建订单并支持重试机制。
    :param goods_id: 商品 ID
    :param user_id: 用户 ID
    :param max_retries: 最大重试次数，默认 3 次
    :param retry_delay: 每次重试之间的延迟时间（秒），默认 1 秒
    :return: 订单创建结果
    """

    redis = RedisHelper()
    stock_key = f'seckill_stock:{goods_id}'
    goods_key = f'goods_detail:{goods_id}'
    lock_key = f"lock:order:{goods_id}"

    # lock_value = redis.acquire_lock(lock_key, expire_time=5)
    # if not lock_value:
    #     raise self.retry(exc=ValueError("无法获取分布式锁"), countdown=1)

    try:
        with transaction.atomic():

            seckillgoods = None
            for attempt in range(max_retries + 1):
                try:
                    seckillgoods = SeckillGoods.objects.select_for_update().get(goods_id=goods_id)
                    break
                except SeckillGoods.DoesNotExist:
                    if attempt == max_retries - 1:
                        logger.error(f"商品 {goods_id} 不存在，已达最大重试次数")
                        raise ValueError("商品不存在")
                    time.sleep(retry_delay)


            # 校验库存
            if seckillgoods.stock_count <= 0:
                logger.error(f"商品 {goods_id} 库存不足")
                raise ValueError("库存不足")

            # 原子扣减SeckillGoods库存
            updated = SeckillGoods.objects.filter(
                id=seckillgoods.id,
                stock_count=seckillgoods.stock_count
            ).update(stock_count=F('stock_count') - 1)
            if not updated:
                logger.warning("SeckillGoods库存更新失败，触发重试")
                raise self.retry(countdown=retry_delay)

            # 扣减Goods表库存
            goods_updated = Goods.objects.filter(
                id=goods_id
            ).update(goods_stock=F('goods_stock') - 1)
            if not goods_updated:
                logger.warning("Goods库存更新失败，触发重试")
                raise self.retry(countdown=retry_delay)
            #获取商品信息
            goods = redis.get_cache(goods_key)
            if not goods:
                return {"code": 400, "message": f"商品 ID {goods_id} 不存在"}

            # 创建普通订单
            order = Order.objects.create(
                user_id=user_id,
                goods_id=goods_id,
                delivery_addr_id=1,  # 示例：默认地址
                goods_name=goods['name'],
                goods_count=1,
                goods_price=seckillgoods.seckill_price,
                order_channel=1,  # 秒杀渠道
                status=0,  # 待支付
            )

            # 创建秒杀订单并关联普通订单
            seckill_order = SeckillOrder.objects.create(
                user_id=user_id,
                goods_id=goods_id,
                order=order,
            )


            # 记录成功日志
            logger.info(f"订单创建成功: 用户 {user_id}, 商品 {goods_id}, 订单号 {order.id}")
            return {
                "code": 200,
                "message": "订单创建成功",
                "data": {
                    "user_id": user_id,
                    "goods_id": goods_id,
                    "order_id": order.id,
                }
            }

    except SeckillGoods.DoesNotExist:

        logger.error(f"SeckillGoods not found for goods_id: {goods_id}")

        return {"code": 400, "message": "商品不存在"}

    except IntegrityError as e:

        logger.error(f"IntegrityError occurred: {str(e)}")

        return {"code": 400, "message": f"订单创建失败：{str(e)}"}

    except ValueError as e:

        logger.error(f"Failed to create order: {str(e)}")

        return {"code": 400, "message": str(e)}


    except OperationalError as e:

        logger.error(f"Database error occurred: {str(e)}")

        raise self.retry(exc=e, countdown=1)


    except Exception as e:

        logger.error(f"Unexpected error occurred: {str(e)}")

        raise self.retry(exc=e, countdown=1)

    finally:
        # if lock_value:  # 确保 lock_value 有效
        #     redis.release_lock(lock_key, lock_value)
        close_old_connections()  # 确保关闭数据库连接


    # goods = Goods.objects.get(id=goods_id)
    # seckillgoods =SeckillGoods.objects.get(goods_id=goods_id)
    # if seckillgoods.stock_count > 0:
    #     order = Order.objects.create(
    #         user_id=user_id,
    #         goods_id=goods_id,
    #         delivery_addr_id=1,  # 示例：默认地址
    #         goods_name=goods.goods_name,
    #         goods_count=1,
    #         goods_price=seckillgoods.seckill_price,
    #         order_channel=1,  # 秒杀渠道
    #         status=0,  # 待支付
    #
    #     )
    #     # 创建秒杀订单并关联普通订单
    #     seckill_order = SeckillOrder.objects.create(
    #         user_id=user_id,
    #         goods_id=goods_id,
    #         order=order,
    #     )
    #     goods.goods_count -= 1
    #     seckillgoods.stock_count-=1
    #     goods.save()
    #     seckillgoods.save()
    #     return f"订单创建成功：用户 {user_id}，商品 {goods['id']}"



# goods.goods_stock -= 1
# seckillgoods.stock_count -= 1
# goods.save()
# seckillgoods.save()

# @shared_task(bind=True, autoretry_for=(DatabaseError,),
#            retry_backoff=True, max_retries=3)
# def createOrder(self, user_id, goods_id):
#     redis_conn = get_redis_connection('seckill')
#     stock_key = f'seckill:stock:{goods_id}'
#     user_lock_key = f'seckill:user_lock:{user_id}:{goods_id}'
#
#     try:
#         # ===== 第三阶段：数据库强校验 =====
#         with transaction.atomic():
#             # 行级锁+乐观锁双重保障
#             seckill_goods = SeckillGoods.objects.select_for_update().get(
#                 goods_id=goods_id,
#                 stock_count__gt=0
#             )
#
#             # 二次校验Redis库存
#             current_stock = redis_conn.get(stock_key)
#             if not current_stock or int(current_stock) < 0:
#                 raise self.retry(countdown=1)
#
#             # 扣减数据库库存（原子操作）
#             updated = SeckillGoods.objects.filter(
#                 id=seckill_goods.id,
#                 stock_count=seckill_goods.stock_count
#             ).update(stock_count=F('stock_count') - 1)
#
#             if not updated:
#                 raise self.retry(countdown=1)
#
#             # ===== 创建订单 =====
#             goods = Goods.objects.get(id=goods_id)
#             order = Order.objects.create(
#                 user_id=user_id,
#                 goods_id=goods_id,
#                 goods_name=goods.goods_name,
#                 goods_price=seckill_goods.seckill_price,
#                 status=0
#             )
#             SeckillOrder.objects.create(
#                 user_id=user_id,
#                 goods=goods,
#                 order=order
#             )
#
#             # ===== 清理Redis锁 =====
#             redis_conn.delete(user_lock_key)
#             return True
#
#     except SeckillGoods.DoesNotExist:
#         # 库存不足时补偿Redis
#         redis_conn.incr(stock_key)
#         redis_conn.delete(user_lock_key)
#         return False
#     except Exception as e:
#         # 异常时触发重试
#         redis_conn.incr(stock_key)
#         redis_conn.delete(user_lock_key)
#         raise self.retry(exc=e)

@shared_task
def preload_seckill_stock_for_event():
    """定时预加载秒杀商品库存"""
    seckill_goods_ids = SeckillGoods.objects.filter(
        start_date__lte=timezone.now(),
        end_date__gte=timezone.now()
    ).values_list('id', flat=True)
    for seckill_goods_id in seckill_goods_ids:
        preload_stock_to_redis(seckill_goods_id)
        """预加载商品信息"""
        get_goods_detail(seckill_goods_id)

@shared_task
def sync_stock_periodically():
    redis = RedisHelper()
    for goods_id in redis.get_all_seckill_goods_ids():
        print(redis.get_all_seckill_goods_ids())
        stock_key = f"seckill_stock:{goods_id}"
        current_stock = redis.get_cache(stock_key)
        goods_key = f'goods_detail:{goods_id}'
        if current_stock is not None:
            with transaction.atomic():
                seckillgoods = SeckillGoods.objects.select_for_update().get(goods_id=goods_id)
                original_stock = seckillgoods.stock_count
                seckillgoods.stock_count = current_stock
                seckillgoods.save()

                # 同步普通商品库存
                Goods.objects.filter(id=goods_id).update(goods_stock=F('goods_stock') - (original_stock - current_stock))
